package com.batchbrake.jobs;

import java.io.BufferedReader;
import java.io.File;
import java.io.IOException;
import java.io.InputStreamReader;
import java.util.ArrayList;
import java.util.List;
import java.util.Observable;
import java.util.StringTokenizer;

import com.batchbrake.main.BatchBrake;
import com.batchbrake.queue.QueueEntity;

public class JobProc extends Observable implements Runnable {
	private String name = null;
	private boolean working = false;
	private QueueEntity job = null;
	private Process proc = null;
	private String status = null;
	private double percent = 0;
	private String eta = null;
	private String fps = null;
	
	public JobProc(String name) {
		this.name = name;
	}
	
	public String getName() {
		return name;
	}
	public void setName(String name) {
		this.name = name;
	}

	public boolean isWorking() {
		return working;
	}
	
	public void setJob(QueueEntity job) {
		this.job = job;
	}
	public QueueEntity getJob() {
		return job;
	}
	
	public String getStatus() {
		return status;
	}
	public void setStatus(String status) {
		this.status = status;
	}

	public double getPercent() {
		return percent;
	}
	public String getEta() {
		return eta;
	}
	public String getFps() {
		return fps;
	}

	public List<String> buildCommandLine(QueueEntity e) {
		List<String> cmd = new ArrayList<String>();
		
		cmd.add("HandBrakeCLI");
		cmd.add("--input");
		cmd.add(e.getInput().toString());
		cmd.add("--output");
		
		if( BatchBrake.outputFolder == null ) {
			cmd.add(e.getOutput().toString());
		} else {
			cmd.add(BatchBrake.outputFolder + File.separator + e.getOutput().getName());
		}
		
		if( (e.getSubtitles() != null) && (e.getSubtitles().size() != 0) ) {
			String subtitles = "";
			String langs = "";
			String encodings ="";
			
			for( int i = 0; i < e.getSubtitles().size(); i++ ) {
				subtitles += e.getSubtitles().get(i).toString();
				encodings += e.getEncodings().get(i);
				langs += e.getLangs().get(i);
				
				if( i < e.getSubtitles().size() - 1 ) {
					subtitles += ",";
					encodings += ",";
					langs += ",";
				}
			}

			cmd.add("--srt-file");
			cmd.add(subtitles);
			cmd.add("--srt-codeset");
			cmd.add(encodings);
			cmd.add("--srt-lang");
			cmd.add(langs);
		}
		if( e.getPreset() != null ) {
			cmd.add("--preset");
			cmd.add(e.getPreset());
			System.out.println("preset not null: " + e.getPreset());
		}
		return cmd;
	}
	
	// Encoding: task 1 of 1, 2.52 %
	// Encoding: task 1 of 1, 2.70 % (250.33 fps, avg 259.69 fps, ETA 00h02m30s)
	public void setJobInfos(String line) {
		StringTokenizer tok = new StringTokenizer(line, ",():%");
		
		if( tok.hasMoreTokens() && (tok.nextToken().equals("Encoding")) ) {
			
			tok.nextToken();
			percent = Double.parseDouble(tok.nextToken());
			
			if( tok.hasMoreTokens() ) {
				tok.nextToken();
				fps = tok.nextToken();
				tok.nextToken();
				eta = tok.nextToken().substring(1);
			}
		}
	}
	
	public void handbrake(QueueEntity e) throws InterruptedException, IOException {
		List<String> cmd = buildCommandLine(e);
		
		for( int i = 0; i < cmd.size(); i++ ) {
			System.err.print(cmd.get(i) + " ");
		}
		System.err.println("");

		proc = Runtime.getRuntime().exec(cmd.toArray(new String[] { }));

		BufferedReader reader = new BufferedReader(new InputStreamReader(proc.getInputStream()));
		String line = null;

		while( ((line = reader.readLine()) != null) ) {
			status = line;
			setJobInfos(line);
			this.setChanged();
			this.notifyObservers(this);
		}			
		int exitValue = proc.waitFor();
		if( exitValue != 0 ) {
			throw new InterruptedException();
		}
	}

	public void stop() {
		if( proc != null ) {
			proc.destroy();
		}
	}
	
	@Override
	public void run() {
		working = true;
		this.setChanged();
		this.notifyObservers(this);
		try {
			handbrake(job);
			job.setJobDone(true);
		} catch( Exception e ) {
			e.printStackTrace();
			job.setJobDone(false);
		}
		working = false;
		job.setProc(null);
		this.setChanged();
		this.notifyObservers(this);
	}
}
